package com.supermap.desktop;

import java.awt.Color;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.sql.Time;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import javax.swing.DefaultCellEditor;
import javax.swing.Icon;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

import com.supermap.data.CursorType;
import com.supermap.data.FieldType;
import com.supermap.data.Recordset;
import com.supermap.data.StatisticMode;
import com.supermap.desktop.Interface.IContextMenu;
import com.supermap.desktop.Interface.IContextMenuManager;
import com.supermap.desktop.Interface.IFormTabular;
import com.supermap.desktop.enums.WindowType;
import com.supermap.desktop.implement.SmStatusbar;
import com.supermap.desktop.tabularview.TabularViewProperties;
import com.supermap.desktop.ui.FormBaseChild;
import com.supermap.desktop.ui.docking.DockingWindow;
import com.supermap.desktop.ui.docking.DockingWindowListener;
import com.supermap.desktop.ui.docking.OperationAbortedException;
import com.supermap.desktop.ui.docking.View;
import com.supermap.desktop.ui.docking.event.WindowClosingEvent;
import com.supermap.desktop.utilties.FieldTypeUtilties;
import com.supermap.desktop.utilties.TabularStatisticUtilties;
import com.supermap.desktop.utilties.TabularTableModel;

public class FormTabular extends FormBaseChild implements IFormTabular {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 序号列的列号，第0列为序号列
	 */
	public static final int SEQUENCED_COLUMN_NUMBER = 0;

	private TabularTableModel tabularTableModel;
	private transient Recordset recordset;
	private JTable jTableTabular;
	private String title = "";
	private JScrollPane jScrollPaneChildWindow;
	private JPopupMenu FormSuperTabularContextMenu;
	private static final Color COLOR_SYSTEM_SELECTED = new Color(185, 214, 244);
	private static final Color COLOR_SYSTEM_NOT_SELECTED = new Color(230, 230, 230);
	private static final Color COLOR_EDITABLE_SELECTED = new Color(196, 225, 255);
	private static final Color COLOR_EDITABLE_NOT_SELECTED = new Color(247, 247, 247);
	private static final Color COLOR_WORD_SELECTED = Color.BLACK;
	private static final Color COLOR_SERIAL_NUMBER_BACKGROUND = Color.WHITE;

	private static final int SERIAL_NUMBER_WIDTH = 60;
	private static final int PREFER_COLUMN_WIDTH = 120;
	private static final int MIN_COLUMN_WIDTH = 20;

	public FormTabular() {
		this("");
	}

	public FormTabular(String name) {
		this(name, null, null);
	}

	public FormTabular(String title, Icon icon, Component component) {
		super(title, icon, component);
		this.title = title;
		jTableTabular = new JTable() {
			private static final long serialVersionUID = 1L;

			@Override
			public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
				Component component = super.prepareRenderer(renderer, row, column);
				if (column == 0) {
					component.setBackground(COLOR_SERIAL_NUMBER_BACKGROUND);
				} else if (!this.isCellEditable(row, column)) {
					if (isCellSelected(row, column)) {
						component.setBackground(COLOR_SYSTEM_SELECTED);
					} else {
						component.setBackground(COLOR_SYSTEM_NOT_SELECTED);
					}
				} else {
					if (isCellSelected(row, column)) {
						component.setBackground(COLOR_EDITABLE_SELECTED);
					} else {
						component.setBackground(COLOR_EDITABLE_NOT_SELECTED);
					}
				}
				return component;
			}
		};
		jScrollPaneChildWindow = new JScrollPane(jTableTabular);
		jScrollPaneChildWindow.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		this.setComponent(jScrollPaneChildWindow);
		if (Application.getActiveApplication().getMainFrame() != null) {
			IContextMenuManager manager = Application.getActiveApplication().getMainFrame().getContextMenuManager();
			this.FormSuperTabularContextMenu = (JPopupMenu) manager.get("SuperMap.Desktop.FormSuperTabular.FormSuperTabularContextMenu");
		}
		jTableTabular.addMouseListener(new MouseAdapter() {
		
			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3 && e.getClickCount() == 1) {
					showContextMenu(e);
				}else if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) {
					TabularStatisticUtilties.updataSatusbars();
				}
			}
			
			@Override
			public void mouseReleased(MouseEvent e){
				TabularStatisticUtilties.updataSatusbars();
			}

		});
		
		this.addListener(new DockingWindowListener() {

			@Override
			public void windowUndocking(DockingWindow window) throws OperationAbortedException {
				// Do nothing
			}

			@Override
			public void windowUndocked(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowShown(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowRestoring(DockingWindow window) throws OperationAbortedException {
				// Do nothing
			}

			@Override
			public void windowRestored(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowRemoved(DockingWindow removedFromWindow, DockingWindow removedWindow) {
				// Do nothing
			}

			@Override
			public void windowMinimizing(DockingWindow window) throws OperationAbortedException {
				// Do nothing
			}

			@Override
			public void windowMinimized(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowMaximizing(DockingWindow window) throws OperationAbortedException {
				// Do nothing
			}

			@Override
			public void windowMaximized(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowHidden(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowDocking(DockingWindow window) throws OperationAbortedException {
				// Do nothing
			}

			@Override
			public void windowDocked(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowClosing(WindowClosingEvent evt) throws OperationAbortedException {
				if (evt.getSource().equals(this)) {
					recordset.dispose();
				}
			}

			@Override
			public void windowClosed(DockingWindow window) {
				// Do nothing
			}

			@Override
			public void windowAdded(DockingWindow addedToWindow, DockingWindow addedWindow) {
				// Do nothing
			}

			@Override
			public void viewFocusChanged(View previouslyFocusedView, View focusedView) {
				// Do nothing
			}
		});
		initStatusbars();
	}

	/**
	 * 设置不可编辑
	 */
	private void initStatusbars(){
		SmStatusbar smStatusbar = this.getStatusbar();
		((JTextField)smStatusbar.get(TabularStatisticUtilties.FIELD_TYPE)).setEditable(false);
		((JTextField)smStatusbar.get(TabularStatisticUtilties.FIELD_NAME)).setEditable(false);
		((JTextField)smStatusbar.get(TabularStatisticUtilties.STATISTIC_RESULT_INDEX)).setEditable(false);
	}
	
	private void showContextMenu(MouseEvent e) {
		FormSuperTabularContextMenu.show(jTableTabular, e.getX(), e.getY());
	}

	@Override
	public String getText() {
		return this.title;
	}

	@Override
	public void setText(String text) {
		this.title = text;
	}

	@Override
	public WindowType getWindowType() {
		return WindowType.TABULAR;
	}

	@Override
	public void windowHidden() {
		// 隐藏
	}

	@Override
	public void windowShown() {
		// 显示
	}

	private void setColumnsWidth() {
		// 设置列宽
		jTableTabular.getColumnModel().getColumn(0).setPreferredWidth(SERIAL_NUMBER_WIDTH);
		jTableTabular.getColumnModel().getColumn(0).setMaxWidth(SERIAL_NUMBER_WIDTH);
		jTableTabular.getColumnModel().getColumn(0).setMinWidth(SERIAL_NUMBER_WIDTH);
		for (int i = 1; i < jTableTabular.getColumnModel().getColumnCount(); i++) {
			// 设置宽度
			jTableTabular.getColumnModel().getColumn(i).setMaxWidth(Integer.MAX_VALUE);
			jTableTabular.getColumnModel().getColumn(i).setMinWidth(MIN_COLUMN_WIDTH);
			jTableTabular.getColumnModel().getColumn(i).setPreferredWidth(PREFER_COLUMN_WIDTH);
		}
	}

	/**
	 * bool类型的渲染器
	 * 
	 * @author XiaJT
	 *
	 */
	private class booleanTableCellRenderer extends JLabel implements TableCellRenderer {

		public booleanTableCellRenderer() {
			super();
		}

		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			if (value == null) {
				this.setText("");
			} else if (value.equals(true)) {
				this.setText("True");
			} else if (value.equals(false)) {
				this.setText("False");
			}
			this.setHorizontalAlignment(JLabel.CENTER);
			return this;
		}
	}

	/**
	 * 日期类型的编辑器
	 * 
	 * @author XiaJT
	 *
	 */
	private class dataTabelCellEditor extends DefaultCellEditor {
		public dataTabelCellEditor(final JTextField textField) {
			super(textField);
			textField.setHorizontalAlignment(JTextField.CENTER);

			this.delegate = new EditorDelegate() {
				@Override
				public void setValue(Object value) {
					SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
					textField.setText((value != null) ? dateFormat.format(value) : "");
				}

				@Override
				public Object getCellEditorValue() {
					return textField.getText();
				}
			};
		}
	}

	/**
	 * 日期类型渲染器
	 * 
	 * @author XiaJT
	 *
	 */
	private class DataTabelCellRender extends JLabel implements TableCellRenderer {

		public DataTabelCellRender() {
			super();
			this.setHorizontalAlignment(JLabel.CENTER);
		}

		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
			this.setText((value != null) ? dateFormat.format(value) : "");
			return this;
		}

	}

	@Override
	public int getRowCount() {
		return this.jTableTabular.getRowCount();
	}

	@Override
	public int getSelectedRow() {
		return this.jTableTabular.getSelectedRow();
	}

	@Override
	public int[] getSelectedRows() {
		return this.jTableTabular.getSelectedRows();
	}

	@Override
	public Recordset getRecordset() {
		return this.tabularTableModel.getRecordset();
	}

	@Override
	public void setRecordset(Recordset recordset) {

		// 数据信息
		if (this.tabularTableModel != null) {
			this.tabularTableModel.dispose();
		}
		this.recordset = recordset;
		this.tabularTableModel = new TabularTableModel(recordset);
		this.jTableTabular.setModel(this.tabularTableModel);

		// 编辑时保存
		TableCellEditor tableCellEditor = jTableTabular.getDefaultEditor(JTable.class);
		tableCellEditor.addCellEditorListener(new CellEditorListener() {

			@Override
			public void editingStopped(ChangeEvent e) {
				int column = jTableTabular.getSelectedColumn();
				int row = jTableTabular.getSelectedRow();
				if (row != -1 && column != -1) {
					((TabularTableModel) jTableTabular.getModel()).updateData(row, column, jTableTabular.getCellEditor(row, column).getCellEditorValue());
				}
			}

			@Override
			public void editingCanceled(ChangeEvent e) {
				// do nothing
			}
		});

		// 设置选中时不默认选中一行或一列
		jTableTabular.setColumnSelectionAllowed(true);
		jTableTabular.setRowSelectionAllowed(true);

		// 设置选中字体颜色不变
		jTableTabular.setSelectionForeground(COLOR_WORD_SELECTED);

		// 序号点击选中一行
		jTableTabular.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (jTableTabular.columnAtPoint(e.getPoint()) == FormTabular.SEQUENCED_COLUMN_NUMBER) {
					int pick = jTableTabular.rowAtPoint(e.getPoint());
					if(e.isControlDown()){
						jTableTabular.addRowSelectionInterval(pick, pick);
					}else {
						jTableTabular.setRowSelectionInterval(pick, pick);
					}
					
					if (jTableTabular.getColumnCount() > 0) {
						jTableTabular.setColumnSelectionInterval(0, jTableTabular.getColumnCount() - 1);
					}
				}
			}
		});

		// 表头点击选中一列
		jTableTabular.getTableHeader().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				// 获取点击的列索引
				int pick = jTableTabular.getTableHeader().columnAtPoint(e.getPoint());
				// 设置选择模型
				if (pick < jTableTabular.getColumnCount() && pick >= 0) {
					if(e.isControlDown()){
						jTableTabular.addColumnSelectionInterval(pick, pick);
					}else {
						jTableTabular.setColumnSelectionInterval(pick, pick);
					}
					if (jTableTabular.getRowCount() > 0) {
						jTableTabular.setRowSelectionInterval(0, jTableTabular.getRowCount() - 1);
					}
				}
				TabularStatisticUtilties.updataSatusbars();
			}
		});
		// 设置多选可用
		jTableTabular.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

		// 不拖动
		jTableTabular.getTableHeader().setReorderingAllowed(false);

		// 设置居中显示
		DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer();
		cellRenderer.setHorizontalAlignment(JTextField.CENTER);
		jTableTabular.setDefaultRenderer(Object.class, cellRenderer);

		jTableTabular.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

		((DefaultTableCellRenderer) jTableTabular.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(JLabel.CENTER);
		// bool类型编辑器
		JComboBox<String> booleanEditorControl = new JComboBox<String>();
		booleanEditorControl.addItem("");
		booleanEditorControl.addItem("True");
		booleanEditorControl.addItem("False");
		DefaultCellEditor booleanEditor = new DefaultCellEditor(booleanEditorControl);
		this.jTableTabular.setDefaultEditor(Boolean.class, booleanEditor);

		this.jTableTabular.setDefaultRenderer(Boolean.class, new booleanTableCellRenderer());

		this.jTableTabular.setDefaultEditor(Time.class, new dataTabelCellEditor(new JTextField()));
		this.jTableTabular.setDefaultRenderer(Time.class, new DataTabelCellRender());
		JTextField objectEditorControl = new JTextField();
		objectEditorControl.setHorizontalAlignment(JTextField.CENTER);
		DefaultCellEditor objectCellEditor = new DefaultCellEditor(objectEditorControl);
		this.jTableTabular.setDefaultEditor(Object.class, objectCellEditor);
		setColumnsWidth();
		this.jTableTabular.updateUI();
		TabularStatisticUtilties.updataSatusbars();
	}

	/**
	 * 定位函数
	 */
	@Override
	public void goToRow(int goToRow) {
		this.jTableTabular.clearSelection();
		this.jTableTabular.setRowSelectionInterval(goToRow, goToRow);
		this.jTableTabular.setColumnSelectionInterval(0, jTableTabular.getColumnCount() - 1);
		Rectangle aRect = this.jTableTabular.getCellRect(goToRow, 0, true);
		this.jTableTabular.scrollRectToVisible(aRect);
	}

	@Override
	public int getSelectColumnCount() {
		return this.jTableTabular.getSelectedColumnCount();
	}

	@Override
	public int[] getSelectedColumns() {
		return this.jTableTabular.getSelectedColumns();
	}

	@Override
	public Object getValueAt(int row, int column) {
		return this.jTableTabular.getModel().getValueAt(row, column);
	}

	@Override
	public boolean sortRecordset(String sortKind, int... selectedColumns) {
		boolean flag = false;
		this.recordset = ((TabularTableModel) this.jTableTabular.getModel()).sortRecordset(sortKind, selectedColumns);
		this.jTableTabular.updateUI();
		if(recordset != null){
			flag = true;
		}
		return flag;
	}

	@Override
	public boolean doStatisticAnalust(StatisticMode statisticMode, String successMessage) {
		int selectColumn = jTableTabular.getSelectedColumn() - 1;
		if (!TabularStatisticUtilties.isStatisticsSupportType(recordset, selectColumn)) {
			TabularStatisticUtilties.updataStatisticsResult(TabularViewProperties.getString("String_Output_ColumnNotStatistic"));
			return false;
		}
		int[] selectedRows = this.getSelectedRows();
		for (int i = 0; i < selectedRows.length; i++) {
			// 第一列为ID
			selectedRows[i] = (int) this.jTableTabular.getModel().getValueAt(selectedRows[i], 1);
		}
		Recordset statisticRecordset = recordset.getDataset().query(selectedRows, CursorType.DYNAMIC);
		double result = statisticRecordset.statistic(selectColumn, statisticMode);
		String columnType = getSelectColumnType(selectColumn);
		String name = getSelectColumnName(selectColumn);
		TabularStatisticUtilties.updataStatisticsResult(MessageFormat.format(successMessage, columnType, name, result));
		return true;
	}

	@Override
	public String getSelectColumnType(int column) {
		FieldType fieldType = recordset.getFieldInfos().get(column).getType();
		return FieldTypeUtilties.getFieldTypeName(fieldType);
	}

	@Override
	public String getSelectColumnName(int column) {
		return recordset.getFieldInfos().get(column).getName();
	}

}
